package cloudspace.controlpanel;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.util.GenericComposer;
import org.zkoss.zul.Column;
import org.zkoss.zul.Columns;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Row;
import org.zkoss.zul.Rows;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Tabbox;
import org.zkoss.zul.Tabpanel;
import org.zkoss.zul.Tabpanels;
import org.zkoss.zul.Tabs;
import org.zkoss.zul.Window;


public class CompileHelperController extends GenericComposer
{

    private static final String FILE_CONTENT = "fileData";

    private Window self;

    /**
	 * 
	 */
    private static final long serialVersionUID = 1956588549278805597L;


    public void doAfterCompose( Component comp ) throws Exception
    {
        super.doAfterCompose( comp );
        self = (Window)comp;
        Executions.getCurrent()
            .getDesktop()
            .setAttribute( "CompileHelper", self );
    }


    public void onUpdate( Event event )
    {
        try
        {
            int nonDisplay = 0;
            @SuppressWarnings("unchecked")
            DiagnosticCollector<JavaFileObject> errorDetails = (DiagnosticCollector<JavaFileObject>)event.getData();
            @SuppressWarnings("unchecked")
            List<File> compiledFiles = (List<File>)Executions.getCurrent()
                .getDesktop()
                .getAttribute( "compiledFiles" );
            Tabbox editBox = (Tabbox)self.getFellow( "editBox" );
            Tabs topTabs = editBox.getTabs();
            topTabs.getChildren().clear();
            Tabpanels panels = editBox.getTabpanels();
            panels.getChildren().clear();
            Map<File, List<Diagnostic<? extends JavaFileObject>>> fileToError = new HashMap<File, List<Diagnostic<? extends JavaFileObject>>>();
            for ( File compiledFile : compiledFiles )
            {
                fileToError.put( compiledFile,
                    new ArrayList<Diagnostic<? extends JavaFileObject>>() );
            }
            for ( Diagnostic<? extends JavaFileObject> diagnostic : errorDetails.getDiagnostics() )
            {
                for ( File key : fileToError.keySet() )
                {
                    if ( diagnostic.getKind() != Diagnostic.Kind.ERROR )
                    {
                        nonDisplay++;
                        break;
                    }
                    if ( diagnostic.getSource() != null
                        && key.getName().equals( diagnostic.getSource()
                            .getName() ) )
                    {
                        fileToError.get( key ).add( diagnostic );
                        break;
                    }
                }
            }
            for ( File compiledFile : fileToError.keySet() )
            {
                if ( fileToError.get( compiledFile ).size() == 0 )
                {
                    continue;
                }
                Tab fileTab = new Tab( compiledFile.getName() );
                topTabs.appendChild( fileTab );

                Tabpanel panel = new Tabpanel();
                panel.setStyle( "overflow: auto" );
                panels.appendChild( panel );

                Grid fileContents = new Grid();
                fileContents.setVflex( true );
                fileContents.setHeight( "100%" );
                fileContents.setParent( panel );

                Rows content = new Rows();
                content.setId( FILE_CONTENT + compiledFile.getName() );
                content.setParent( fileContents );
                Columns columns = new Columns();
                Column numberColumn = new Column( "#" );
                numberColumn.setWidth( "40px" );
                Column fileColumn = new Column( "File" );
                numberColumn.setParent( columns );
                fileColumn.setParent( columns );
                columns.setParent( fileContents );

                Reader fileReader = new FileReader( compiledFile );
                BufferedReader sourceReader = new BufferedReader( fileReader );
                String line = sourceReader.readLine();

                int lineNumber = 1;
                while ( line != null )
                {
                    Row numberAndLine = new Row();
                    numberAndLine.setParent( content );
                    Label lineNumberLabel = new Label( "" + lineNumber );
                    lineNumber++;
                    lineNumberLabel.setParent( numberAndLine );
                    Label fileText = new Label();
                    fileText.setMultiline( true );
                    fileText.setPre( true );
                    fileText.setValue( line );
                    fileText.setParent( numberAndLine );
                    line = sourceReader.readLine();

                }
                Label errorTitle = new Label( "Errors:" );
                errorTitle.setStyle( "font-size: larger" );
                errorTitle.setParent( panel );
                Listbox errorBox = new Listbox();
                errorBox.setRows( 5 );
                for ( Diagnostic<? extends JavaFileObject> diagnostic : fileToError.get( compiledFile ) )
                {
                    Listitem item = new Listitem();
                    item.setValue( diagnostic );
                    String[] splitMessage = diagnostic.getMessage( null )
                        .split( ":" );
                    item.setLabel( compiledFile.getName() + ":"
                        + splitMessage[1] + ":" + splitMessage[2] );
                    item.setParent( errorBox );

                }
                errorBox.setParent( panel );
            }
            Tab compTab = (Tab)self.getPage().getFellow( "compTab" );
            if ( errorDetails.getDiagnostics().size() - nonDisplay != 0 )
            {
                compTab.setSelected( true );
                compTab.setVisible( true );
                compTab.setDisabled( false );
                compTab.setImage( "icons/tab-compile-bad.png" );
            }
            else
            {
                compTab.setVisible( true );
                compTab.setDisabled( true );
                compTab.setImage( "icons/tab-compile-good.png" );
            }
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
        finally
        {
            event.stopPropagation();
        }
    }
    /*
     * private void highlightSelected(Diagnostic<? extends JavaFileObject>
     * selectedDiag) throws IOException { if(previousColored.size() != 0) {
     * for(Label previous : previousColored) { previous.setStyle(""); }
     * previousColored.clear(); }
     * 
     * Rows fileContent = (Rows)
     * self.getFellow(FILE_CONTENT+selectedDiag.getSource().getName()); // This
     * could be a problem but really who writes a Java // file with more // than
     * 4294967296 lines. I suppose this is a feature // :-). Label startLine =
     * getFileLineToLabel( (int) selectedDiag.getLineNumber() - 1, fileContent);
     * CharSequence seq = selectedDiag.getSource().getCharContent(true); int
     * position = (int) selectedDiag.getStartPosition(); char backstep =
     * seq.charAt(position); while (backstep != '\n') { backstep =
     * seq.charAt(position--); } int offset = 0; int endPosition = (int)
     * selectedDiag.getEndPosition(); while (position <= endPosition) {
     * offset++; position += startLine.getValue().length();
     * startLine.setStyle("background-color: #F62217; color: white;");
     * previousColored.add(startLine); startLine = getFileLineToLabel((int)
     * selectedDiag.getLineNumber() - 1 + offset, fileContent);
     * 
     * } }
     * 
     * private Label getFileLineToLabel(int fileLine, Rows fileContent) { Row
     * fileLineRow = (Row) fileContent.getChildren().get(fileLine); return
     * (Label) fileLineRow.getChildren().get(1); }
     */
}
